package com.waidi.clothespad.mqttclient;

import android.os.Handler;
import android.util.Log;
import com.waidi.clothespad.common.Config;
import com.waidi.clothespad.common.MessageToUi;
import com.waidi.clothespad.common.RealData;
import com.waidi.clothespad.common.WorkerInfo;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MyMqttClient extends Thread{

    public static String TAG = "MyMqttClient";
    public Handler handler0 = null;//selef
    public Handler handler1 = null; //mainActivity handler
    public Handler handler2 = null; //fragrealinfo hadndler
    public Handler handler3 = null;


    public static String passWord="admin";
    public static String userName="admin";

    //public static String myTopic[]={Config.devConfig.devid,};

    public static String myTopic=null;

    public static String clientId= null;
    public static String broker= null;
    public static int qos = 2;
    public static int timeout = 4000;
    public static MemoryPersistence persistence =null;
    public static MqttConnectOptions connOpts = null;
    public static MqttClient myClient = null;

    public static boolean myClientConn= false;
    public static ArrayList<Action> actionArrayList = new ArrayList<Action>();

  //  private static MqttAndroidClient myClient;
    public static MqttCallbackExtended mqttCallback = null;

    public MyMqttClient()
    {

        Action tmp1 = new Action("dg.worker.info.update",1);
        actionArrayList.add(tmp1);
        Action tmp2 = new Action("timer.workerinfo.sync",2);
        actionArrayList.add(tmp2);
        Action tmp3 = new Action("real.info",3);
        actionArrayList.add(tmp3);
        Action tmp4 = new Action("mq.lastCostTime",4);
        actionArrayList.add(tmp4);
        Action tmp5 = new Action("orderReturnHgInfo",5);
        actionArrayList.add(tmp5);
        Action tmp6 = new Action("mq.stateCode",6);
        actionArrayList.add(tmp6);

        Action tmp7 = new Action("order.return",7);
        actionArrayList.add(tmp7);



        Log.i(TAG,"actionArrayList:"+actionArrayList.size());


    }


    public void initMqttOptions()
    {
        // 清除缓存
        connOpts = new MqttConnectOptions();
        connOpts.setCleanSession(true);
        connOpts.setPassword(passWord.toCharArray());
        connOpts.setUserName(userName);
        // 设置超时时间，单位：秒
        connOpts.setConnectionTimeout(timeout/1000);
        // 心跳包发送间隔，单位：秒
        connOpts.setKeepAliveInterval(30);
        connOpts.setMaxInflight(10);
        //不要自动连接，自己手动连接
        //connOpts.setAutomaticReconnect(true);

    }

    public static int ttt = 0;
    public  static void initMqttCallback()
    {
        mqttCallback=new MqttCallbackExtended()
        {
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                Log.i(TAG, "connect Complete "+ Config.devConfig.addr+" ok tid:" + Thread.currentThread().getId());
                try
                {
                    myClientConn = true;
                    if(myClient!=null)
                        myClient.subscribe(myTopic,qos);//设置监听的topic
                    new MessageToUi().send(1,"mq.statue","connect",Config.MainActivityHandler);
                }
                catch (MqttException e)
                {
                    myClientConn = false;
                    Log.e(TAG,e.toString());
                    disConnectBroker();

                }

            }

            @Override
            public void connectionLost(Throwable cause)
            {
                Log.i(TAG, "connection Lost ");
                myClientConn = false;
                new MessageToUi().send(1,"mq.statue","disconnect",Config.MainActivityHandler);
            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                Log.i(TAG, "topic:"+topic+" palyload:"+new String(message.getPayload()));

                ttt++;
                if(ttt>2)
                {
                    new MessageToUi().send(1,"mq.statue","connect",Config.MainActivityHandler);
                    ttt = 0;
                }

                if(topic.equalsIgnoreCase(myTopic))
                {
                    try
                    {
                        JSONObject jsonObj = new JSONObject(new String(message.getPayload()));
                        if (jsonObj == null)
                            return;
                        if(jsonObj.has("action")==true)
                        {
                            String action =  jsonObj.optString("action");
                            int i ,code = 0;
                            for (i = 0;i<actionArrayList.size();i++)
                            {
                                if(actionArrayList.get(i).type.compareTo(action)==0)
                                {
                                    code = actionArrayList.get(i).code;
                                    break;
                                }
                            }
                            Log.i(TAG,"out->"+code);
                            switch (code)
                            {
                                case 1:
                                    workerLogo(jsonObj);
                                    break;
                                case 2:
                                    workerLogoout(jsonObj);
                                    break;
                                case 3:
                                    hangerRealinfo(jsonObj);
                                    break;
                                case 4:
                                   // workerTailorEfficiency(jsonObj);
                                    break;
                                case 5:
                                    break;
                                case 6:
                                    break;

                                case 7:
                                    returnErrMessage(jsonObj);
                                    break;

                                    default:
                                        Log.i(TAG,"out-> not found"+code);
                            }
                        }
                    }
                    catch (JSONException e)
                    {
                        Log.i(TAG,e.toString());
                    }
                    /*
                    catch (ParseException n)
                    {
                        n.printStackTrace();
                    }
                    catch (FileNotFoundException s)
                    {
                        s.printStackTrace();
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                    */
                }
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token)
            {
                Log.i(TAG, "delivery Complete ");//即服务器成功delivery消息
                new MessageToUi().send(1,"mq.statue","connect",Config.MainActivityHandler);
            }

        };
    }
    public static void workerLogo(JSONObject jsonObj)
    {
        try
        {
            if (jsonObj == null)
                return;

            if(jsonObj.has("data")==true)
            {
                JSONObject dataobj =  jsonObj.optJSONObject("data");
                if(dataobj!=null)
                {
                    String workername = dataobj.optString("name");
                    String workercode = dataobj.optString("code");
                    Config.rfidWorkerInfo.workername = workername;
                    Config.rfidWorkerInfo.workernum = workercode;

                    //覃工 没传过来
                    String line = (myTopic.length()>=6?myTopic.substring(0,4):myTopic);

                    Config.rfidWorkerInfo.line = line;


                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String t=format.format(new Date());
                    Config.rfidWorkerInfo.logtime = t;

                    String isLogon = dataobj.optString("islogin");
                    Log.i(TAG,"isLogin:"+isLogon);

                    if(Config.rfidWorkerInfo.workernum.length()==0||
                            Config.rfidWorkerInfo.workername.length()==0
                            ||isLogon.compareTo("0")==0)
                    {
                        Config.rfidWorkerInfo.workername = "未登录";
                        Config.rfidWorkerInfo.workernum="";
                        Config.rfidWorkerInfo.logtime = "0000-00-00 00:00:00";
                    }


                    Config.rfidworkerinfosave();

                    WorkerInfo tmp = new WorkerInfo();
                    tmp.name = workername;
                    tmp.id = workercode;
                    tmp.line = line; //覃工 没传过来
                    tmp.logontime = t;

                    new MessageToUi().sendParcelable(801,"dg.worker.info.update",tmp,Config.fragShishishuju.handler);
                    new MessageToUi().sendParcelable(801,"dg.worker.info.update",tmp,Config.MainActivityHandler);

                }
            }
        }
        catch (Exception e)
        {
            Log.i(TAG,e.toString());
        }
    }

    public static void workerLogoout(JSONObject jsonObj)
    {
        try
        {
            if (jsonObj == null)
                return;
            if(jsonObj.has("data")==true)
            {
                JSONObject dataobj =  jsonObj.optJSONObject("data");
                if(dataobj!=null)
                {
                    String isLogon = dataobj.optString("islogin");
                    Log.i(TAG,"isLogin:"+isLogon);

                    if(isLogon.compareTo("0")==0)
                    {
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String t = format.format(new Date());
                        Config.rfidWorkerInfo.logtime = t;

                        Config.rfidWorkerInfo.workernum = "";
                        Config.rfidWorkerInfo.workername = "未登录";
                        Config.rfidWorkerInfo.logtime = "0000-00-00 00:00:00";

                        WorkerInfo tmp = new WorkerInfo();
                        tmp.name = "未登录";
                        tmp.id = "";
                        tmp.line = "";
                        tmp.logontime = t;
                        Config.rfidworkerinfosave();
                        new MessageToUi().sendParcelable(801, "dg.worker.info.update", tmp, Config.fragShishishuju.handler);
                        new MessageToUi().sendParcelable(801,"dg.worker.info.update",tmp,Config.MainActivityHandler);
                    }

                    if(isLogon.compareTo("1")==0)
                    {
                        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String t = format.format(new Date());
                        Config.rfidWorkerInfo.logtime = t;

                        Config.rfidWorkerInfo.workernum = dataobj.optString("code");
                        Config.rfidWorkerInfo.workername = dataobj.optString("name");

                        WorkerInfo tmp = new WorkerInfo();
                        tmp.name = dataobj.optString("name");
                        tmp.id = dataobj.optString("code");

                        tmp.logontime = t;
                        Config.rfidworkerinfosave();
                        new MessageToUi().sendParcelable(801, "dg.worker.info.update", tmp, Config.fragShishishuju.handler);
                        new MessageToUi().sendParcelable(801,"dg.worker.info.update",tmp,Config.MainActivityHandler);
                    }
                }
            }
        }
        catch (Exception e)
        {
            Log.i(TAG,e.toString());
        }
    }
    public static void hangerRealinfo(JSONObject jsonObj)
    {
        try
        {
            if (jsonObj == null)
                return;
            if(jsonObj.has("data")==true)
            {
                JSONObject dataobj =  jsonObj.optJSONObject("data");
                if(dataobj!=null)
                {
                    JSONObject jsonObj_realinfo_data = jsonObj.optJSONObject("data");

                    RealData data = new RealData();
                   // data.line_number = jsonObj_realinfo_data.optString("line_number");
                   // data.work_station = jsonObj_realinfo_data.optString("work_station");
                   // data.worker_id = jsonObj_realinfo_data.optString("worker_id");
                    //data.worker_name = jsonObj_realinfo_data.optString("worker_name");
                    //data.style_id = jsonObj_realinfo_data.optString("style_id");
                    data.style_size = jsonObj_realinfo_data.optString("SizeNo");
                    data.order_id = jsonObj_realinfo_data.optString("order_id");
                    data.lineproject = jsonObj_realinfo_data.optString("RouteName");
                    data.hangerid = jsonObj_realinfo_data.optString("card_no");

                    //data.opera_code = jsonObj_realinfo_data.optString("opera_code");
                   // data.opera_desc = jsonObj_realinfo_data.optString("opera_desc");
                    data.style_colour = jsonObj_realinfo_data.optString("ColorNo");

                    new MessageToUi().sendParcelable(2,"real.info",data,Config.fragShishishuju.handler);

                    Config.globalrealhangerid = data.hangerid;
                    Config.schemaLineNum = data.lineproject;
                    if(Config.fragShenglineqc2!=null)
                    {
                        Config.fragShenglineqc2.get_ok = false;
                        new MessageToUi().send(803, "timer.order.return.cardNo", "", Config.fragShenglineqc2.handler);
                    }

                }
            }
        }
        catch (Exception e)
        {
            Log.i(TAG,e.toString());
        }
    }

    public static void returnErrMessage(JSONObject jsonObj)
    {
        try
        {
            if (jsonObj == null)
                return;
            if(jsonObj.has("data")==true)
            {
                JSONObject dataobj =  jsonObj.optJSONObject("data");
                if(dataobj!=null)
                {
                    JSONObject data = jsonObj.optJSONObject("data");
                    String msg = data.optString("msg");
                    new MessageToUi().send(44,"order.return",msg,Config.fragShenglineqc2.handler);
                }
            }
        }
        catch (Exception e)
        {
            Log.i(TAG,e.toString());
        }
    }


    public static void workerTailorEfficiency(JSONObject jsonObj)
    {
        try
        {
            if (jsonObj == null)
                return;
            if(jsonObj.has("data")==true)
            {
                JSONObject dataobj =  jsonObj.optJSONObject("data");
                if(dataobj!=null)
                {
                    new MessageToUi().send(3,"mq.lastCostTime","workerTailorEfficiency",Config.fragShishishuju.handler);
                }
            }
        }
        catch (Exception e)
        {
            Log.i(TAG,e.toString());
        }
    }

    public static int once = 0;
    public static void connectBroker()
    {
       try
       {
           //if(once==0)
           {
               persistence = new MemoryPersistence();
               //once = 1;
           }
           broker="tcp://"+Config.devConfig.addr+":1883";
           clientId=Config.qrCodeInfo.location+"(v"+Config.ver+")#t10:"+Config.getUniquePsuedoID().replace("-","");
           myTopic = (Config.qrCodeInfo.location.length()==0)?"devNoBound?":Config.qrCodeInfo.location;
           myClient = new MqttClient(broker, clientId, persistence);
           myClient.setCallback(mqttCallback);
           myClient.connect(connOpts);
       }
       catch(MqttException me)
       {
           Log.i(TAG,"reason "+me.getReasonCode());
           Log.i(TAG,"msg "+me.getMessage());
           Log.i(TAG,"loc "+me.getLocalizedMessage());
           Log.i(TAG,"cause "+me.getCause());
           Log.i(TAG,"excep "+me);
           me.printStackTrace();
           myClientConn = false;
       }
    }

    public static void disConnectBroker()
    {
        try
        {
            if(myClient!=null)
            {
                myClient.disconnect();
                myClientConn = false;
            }
        }
        catch (MqttException ee)
        {
            Log.i(TAG,"excep "+ee);
        }
    }

    public static void publish( String topic,String s)
    {
        MqttMessage msg=new MqttMessage();
        String msgStr=s;
        try
        {
            Log.i(TAG,"publish:"+msgStr);
            msg.setPayload(msgStr.getBytes());//设置消息内容
            msg.setQos(qos);//设置消息发送质量，可为0,1,2.
            msg.setRetained(false);//服务器是否保存最后一条消息，若保存，client再次上线时，将再次受到上次发送的最后一条消息。

            topic = "/its/padmessage";

            if(myClientConn)
                myClient.publish(topic,msg);//设置消息的topic，并发送。
        }
        catch (MqttPersistenceException e)
        {
            Log.i(TAG,"Persistenceexcep "+e);
        }
        catch (MqttException ee)
        {
            Log.i(TAG,"excep "+ee.toString());
        }
    }
    public void run()
    {

        String brokerIp = Config.devConfig.addr;
        String devid = Config.qrCodeInfo.location;
        try
        {
            initMqttOptions();
            initMqttCallback();
            connectBroker();
            sleep(8000);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        while (true)
        {
            try
            {
                if(myClient.isConnected()==false||myClientConn==false)
                {
                    new MessageToUi().send(1,"mq.statue","disconnect",Config.MainActivityHandler);
                    //this.disConnectBroker();
                    Log.i(TAG,"mqtt client reconnect。。。。。");
                    initMqttOptions();
                    initMqttCallback();
                    connectBroker();
                    Thread.sleep(8000);
                }
                else
                {

                }

                if(brokerIp.compareTo(Config.devConfig.addr)!=0
                        ||devid.compareTo(Config.qrCodeInfo.location)!=0)
                {
                    brokerIp = Config.devConfig.addr;
                    devid = Config.qrCodeInfo.location;
                    Log.i(TAG,"mqtt client reconnect as brokerIp or dev id changed");

                    this.disConnectBroker();
                    new MessageToUi().send(1,"mq.statue","disconnect",Config.MainActivityHandler);

                }
               Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
                Log.i(TAG,"Thread "  + " interrupted.");
                e.printStackTrace();
            }
            catch (Exception t)
            {
                t.printStackTrace();
            }
        }
    }

    public static void qc_repair()
    {
        try
        {
            String returnCode = Config.RePairCodeString ;
            Config.RePairCodeString = "";

            JSONObject requestqc = new JSONObject();
            requestqc.put("action", "order.return");
            JSONObject data = new JSONObject();
            data.put("devid", Config.qrcode);
            String locaton=Config.qrCodeInfo.location;
            data.put("location", locaton);
            data.put("failInfo",returnCode);
            data.put("cardno", Config.globalrealhangerid);

            requestqc.put("data",data);
            publish(Config.qrCodeInfo.location,requestqc.toString());
            Log.i(TAG,requestqc.toString());

        }catch (JSONException e)
        {
            Log.i(TAG,e.toString());
            e.printStackTrace();
        }
    }

    public static void workerSyncToDg(int isloginArg,String workcode)
    {
        try
        {
            //注销同步 //mqtt服务未连接的时候，不进行同步，因为这样存在不知道某个时刻
            JSONObject workinfosync = new JSONObject();
            workinfosync.put("action", "timer.workerinfo.sync");
            JSONObject data = new JSONObject();

            data.put("devid", Config.qrcode);
            String locaton =Config.qrCodeInfo.location;
            data.put("location", locaton);
            data.put("empcode", workcode);

            String islogin = "1";
            if(isloginArg==0)
            {
                islogin = "0";
            }

            data.put("islogin", islogin);
            workinfosync.put("data",data);

            publish(Config.qrCodeInfo.location,workinfosync.toString());
            Log.i(TAG,workinfosync.toString());

        }catch (JSONException e)
        {
            Log.i(TAG,e.toString());
            e.printStackTrace();
        }

    }


    public static void switchSyncToDg(int isOnline,JSONObject jsonObjData)
    {
        try
        {
            //注销同步 //mqtt服务未连接的时候，不进行同步，因为这样存在不知道某个时刻
            JSONObject switchSyncToDg = new JSONObject();
            switchSyncToDg.put("action", "toonline");
            JSONObject data = new JSONObject();
           // data.put("data", jsonObjData);
            switchSyncToDg.put("data",jsonObjData);
            String topic = "/its/padmessage";
            publish(topic,switchSyncToDg.toString());
            Log.i(TAG,"topic:"+topic+"#"+switchSyncToDg.toString());

        }catch (JSONException e)
        {
            Log.i(TAG,e.toString());
            e.printStackTrace();
        }
    }

    public final class Action
    {
        public String type;
        public int code;
        public Action(String type,int code)
        {
            this.type = type;
            this.code = code;
        }
    }
}
